/*
 * @Author: wuqingchun
 * @Date: 2023-12-28 23:48:52
 * @Description: 
 * @LastEditors: wuqingchun
 * @LastEditTime: 2024-01-11 15:39:39
 */
#ifndef __FTPC_H__
#define __FTPC_H__

#include <sys/time.h>

#include "ftpc_buf.h"
#include "ftpc_pi.h"
#include "ftpc_event.h"


/*
MINIMUM IMPLEMENTATION
*/
#define FTPC_CMD_USER           "USER"
#define FTPC_CMD_PASS           "PASS"
#define FTPC_CMD_PASV           "PASV"  //PASSIVE 请求服务端在选择一个数据端口进行监听，等待客户端建立数据连接
#define FTPC_CMD_QUIT           "QUIT"
#define FTPC_CMD_PORT           "PORT"
#define FTPC_CMD_RETR           "RETR"  // RETRIEVE
#define FTPC_CMD_STOR           "STOR"  // STORE
#define FTPC_CMD_TYPE           "TYPE"
#define FTPC_CMD_MODE           "MODE"
#define FTPC_CMD_STRU           "STRU"
#define FTPC_CMD_NOOP           "NOOP"
#define FTPC_CMD_LIST           "LIST"


#define FTPC_CMD_SEPERATOR      " "     // 分隔符
#define FTPC_CMD_EOL            "\r\n"  // 行结束符



// ftp 服务知名端口号
#define FTPC_SERVER_PORT_DEFAULT 21



#define FTPC_CLIENT_HOSTNAME_MAX 255

#define FTPC_CMD_MAXLEN 1023


#define FTP_USER_NAME_MAXLEN 15
#define FTP_PASSWD_MAXLEN 31

#define FTPC_CLIENT_BUF_MAXLEN 1023

#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))

#define BIT_SET(flag, bit) ((flag) |= (bit))
#define BIT_CLR(flag, bit) ((flag) &= ~(bit))
#define BIT_TEST(flag, bit)  (((flag) & (bit)) == (bit))


// 标志位定义
#define FTPC_FLAG_PASSIVE                          0x1   // 服务端使用被动模式标志
#define FTPC_FLAG_DEBUG                            0x2   // 是否启用调试模式
#define FTPC_FLAG_STREAM                           0x4   // 数据传输模式为流模式
#define FTPC_FLAG_GET_DATA                         0x8   // 获取数据

// 命令支持最多参数个数
#define FTPC_CMD_ARG_COUNT_MAX 8

// 发送数据时使用的模式
typedef enum tagFTPCSendMode
{
    FTPC_SEND_MODE_NORMAL = 0,
    FTPC_SEND_MODE_MMAP = 1,
    FTPC_SEND_MODE_SENDFILE = 2,
    FTPC_SEND_MODE_DIRECT_IO = 3,
}FTPC_SEND_MODE_E;

// 数据传输类型
typedef enum tagFTPCTransferType
{
    FTPC_TRANSFER_LIST = 0,
    FTPC_TRANSFER_GET = 1,
    FTPC_TRANSFER_PUT = 2,
    FTPC_TRANSFER_MAX,
}FTPC_TRANSFER_TYPE_E;

// 命令行参数
typedef struct tagFTPCCmdInfo
{
    char* apcItems[FTPC_CMD_ARG_COUNT_MAX];
    unsigned int uiCount;
}FTPC_CMD_INFO_S;

typedef enum tagFTPCState
{
    FTPC_STATE_INIT,
    FTPC_STATE_CONNECTED,
    FTPC_STATE_LOGIN_USER,
    FTPC_STATE_LOGIN_PASSWD,
    FTPC_STATE_LOGIN_SUCCESS,
    FTPC_STATE_LOGIN_FAILED,
    FTPC_STATE_DISCONNECTED,
    FTPC_STATE_NEGOTIATE_PORT,       // 数据端口协商
    FTPC_STATE_TO_DATA_TRANSFER,     // 准备数据传输
    FTPC_STATE_IN_DATA_TRANSFER,
    FTPC_STATE_QUIT,
    FTPC_STATE_MAX,
}FTPC_STATE_E;

// 发送上下文
typedef struct tagFTPCDtpContext
{
    FTPC_TRANSFER_TYPE_E enTransferType;
    FTPC_SEND_MODE_E enSendMode;
    unsigned long ulTotalLen;
    unsigned long ulTransferLen;
    void *pAddr;
    int iListenSock;       // data listen connection
    int iDataSock;         // data connection
    int iTransferFd;
    struct timeval stTValStart;
    struct timeval stTValEnd;
    char* pcDirectIO;
}FTPC_DTP_CONTEXT_S;

typedef struct tagFTPCClient
{
    FTPC_STATE_E enState;
    FTPC_STATE_E enRecoverState;
    int iCtlSock;                // control connection
    FTPC_BUF_HEAD_S stCtlBuf;
    FTPC_BUF_HEAD_S stDataBuf;
    FTPC_PI_CONTEXT_S stPICtx;
    char szHostName[FTPC_CLIENT_HOSTNAME_MAX + 1];
    unsigned short usPort;
    FTPC_EVENT_S stEvent;
    char* pcTransferCmd;
    unsigned int uiFlags;    // 标志位
    char szCmdLine[4096];
    FTPC_CMD_INFO_S stCmdInfo;
    FTPC_DTP_CONTEXT_S stDTPCtx;
}FTPC_CLIENT_S;

extern FTPC_CLIENT_S g_stFTPCClient;

#endif //__FTPC_H__